# @Time : 2024-11-14 11:46
# @Author : Fioman 
# @Phone : 13149920693
"""
向Eap发送请求的模块,主要是请求的一些功能函数
"""
import json

import requests

from db_tools.db_handler import DbHandler
from eap_control import eap_tool
from eap_control.data_model import EapConstant, JobCountType, AlarmType
from eap_control.eap_config import EapConfig
from eap_control.eap_debug import debug_eap
from tools.send_to_ui_tools import update_msg_send

ec = EapConfig()
db = DbHandler()

headers = {
    'Content-Type': 'application/json'
}
_timeout = 2


def request_data_to_eap(methodName, data):
    """
    向Eap发送请求,data是封装好请求的data,包括request_head和request_body
    @param methodName: 请求的方法
    @param data:
    @return:
    """
    url = f"{ec.reqeustUrlFix}{methodName}"
    json_data = json.dumps(data)
    try:
        debug_eap(f"Send To Eap: {methodName}, {json_data} \n")
        update_msg_send(data)
        resp = requests.post(url, headers=headers, data=json_data, timeout=_timeout)
        debug_eap(f"Eap Response: {methodName}, {resp.text} \n")
    except Exception as e:
        debug_eap(f"Eap不在线, {methodName} 请求超时. {str(e)}")
        return EapConstant.TimeOut
    return resp


def request_cim_mode_change_report(cimModeNew):
    """
    调用时机: cim_mode发生改变的时候调用,比如从Local到Remote,或者是从Remote到Local的时候调用
    @return:
    """
    methodName = "CIMModeChangeReport"
    requestHead = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }
    requestBody = {
        "cim_mode": cimModeNew,
        "user_id": ec.userId,
    }
    data = {
        "request_head": requestHead,
        "request_body": requestBody
    }

    return request_data_to_eap(methodName, data)


def request_status_change_report(requestBody):
    """
    向Eap发送 StatusChangeReport 调用时机: 设备状况或者发生改变的时候,和RealStatusReport相似,
    不同的就是如果未上传的状态变更信息,连线之后需要将历史更改信息进行上报
    @return:
    """
    methodName = "StatusChangeReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    request_body = requestBody

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)

def request_alarm_report(alarmType:AlarmType,alarmId:int):
    """
        向Eap发送 StatusChangeReport 调用时机: 设备状况或者发生改变的时候,和RealStatusReport相似,
        不同的就是如果未上传的状态变更信息,连线之后需要将历史更改信息进行上报
        @return:
        """
    requestBody = ec.realStatusData.get_alarm_report_body(alarmType,alarmId)
    methodName = "AlarmReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    request_body = requestBody

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_are_you_there():
    """
    are_you_there_request请求
    @return:
    """
    methodName = "AreYouThere"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    request_body = {
        "now": eap_tool.get_time_stamp(),
        "ip": ec.eqpIp
    }

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_job_count_report(reportType: JobCountType):
    """
    向Eap发送 JobCountReport 请求设备内的在制品数量上报,机台每进一片Count加1,上报JobCountReport,
    退出一片Count减1,上报JobCountReport,也要报出PortNo工位编号,主机台默认报1
    @param reportType:请求上报类型 in或者out,in的时候Count加1,out的时候Count减1,调用时机,
    拍照,识别成功之后调用in,小铡刀第二块铡完之后,调用out
    @return:
    """
    if reportType == JobCountType.In:
        ec.jobCount += 4
    else:
        ec.jobCount -= 1
        if ec.jobCount < 0:
            ec.jobCount = 0
        ec.historyJobCount += 1
        newData = {
            "history_job_count": ec.historyJobCount,
        }
        db.save_eap_config_params(newData)

    methodName = "JobCountReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    request_body = {
        "job_count": ec.jobCount,
        "port_no": ec.portNo,
        "history_job_count": ec.historyJobCount,
    }

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_param_verify(verifyLotId):
    """
    向Eap发送 ParamVerify 调用时机:
    以批号查询相关的制程参数,当设备与Eap连接状态,使用者扫描批号(LOT ID)呼叫WebAPi取得批号相关的资讯
    :param verifyLotId: 以批号查询的相关的参数信息.
    @return:
    """
    methodName = "ParamVerify"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    request_body = {
        "production_mode": ec.productionMode,
        "lot_id": verifyLotId,
    }

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_real_status_report(bodyData):
    """
    向Eap发送 RealStatusReport 即使情况上报(有变化即上报),当设备是连线状态,
    设备状态或者模式有变化的时候就发送此请求
    @return:
    """
    methodName = "RealStatusReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    data = {
        "request_head": request_head,
        "request_body": bodyData
    }
    return request_data_to_eap(methodName, data)


def request_user_verify(verify_user_id, clock_type):
    methodName = "UserVerify"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    request_body = {
        "clock_type": clock_type,
        "user_id": verify_user_id,
    }

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_rtm_report():
    """
    即时监控资料上报,间隔一定时间上报一次,60s到180s之间,默认是180s
    :return:
    """
    methodName = "RTMReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    # 获取要上报的RTM数据,参考Profile文件
    rtm_infos = ec.get_rtm_infos()
    request_body = {
        "report_dt": eap_tool.get_time_stamp(),
        "cim_mode": ec.cimMode,
        "auto_mode": ec.autoMode,
        "status_id": ec.realStatusData.statusId,
        "alarm_id": ec.realStatusData.alarmId,
        "lot_id": ec.lotId,
        "rtm_infos": rtm_infos,
        "attr_infos": {
            "attr": []
        }
    }
    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_wip_tracking_report():
    """
    调用时机: 当前批次的板子完成之后进行上报
    說明：在製品製程結果追蹤報告。
    呼叫時機：當設備與Host AP Server可連線，設備「已做完一個批次(請參考威爾高提供電子化需求)」
    或「設備有未上傳WIP Tracking數據」則呼叫WebAPI。
    在最後一片基板製程結束時，機台必須將該基板資訊、操作人員及相關製程參數上報給BC。
    @return:
    """
    methodName = "WIPTrackingReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }
    # 获取要上报的WTF数据,参考Profile文件
    edc_infos = ec.get_edc_infos()
    request_body = {
        "report_dt": eap_tool.get_time_stamp(),
        "user_id": ec.userId,
        "dept_id": ec.deptId,
        "shift_id": ec.shiftId,
        "start_dt": ec.startDt,
        "end_dt": eap_tool.get_now(),
        "lot_id": ec.lotId,
        "output_qty": ec.outputQty,
        "lot_qty": ec.lotQty,
        "prod_id": ec.prodId,
        "lot_short_id": ec.lotShortId,
        "prod_version": ec.programVersion,
        "prod_mode": ec.prodMode,
        "process_code": ec.processCode,
        "use_in_name": ec.useInName,
        "layer": ec.layer,
        "step_seq": ec.stepSeq,
        "route_type": ec.routeType,
        "rework_route_id": ec.reworkRouteId,
        "rework_step_seq": ec.reworkStepSeq,
        "pnl_side": ec.pnlSide,
        "edc_infos": edc_infos
    }

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_utility_report():
    """
    向Eap发送 UtilityReport 上报时机: 设定上报时间,一个班别结束之后进行上报,比如1号班别代码为:
    1 :  08:00 - 20:00  当日
    2:  20:00 - 08:00 前一日
    超过了当日的20:00分的时候,就上报前一班数据
    比如20:01 分上报班别1
    然后超过了08:00比如08:01的时候上报2号班别的数据
    @return:
    """
    methodName = "UtilityReport"
    request_head = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }

    utl_infos = ec.get_utl__infos()
    request_body = {
        "report_date": eap_tool.get_now(),
        "shift_id": ec.shiftId,
        "utl_infos": utl_infos
    }

    data = {
        "request_head": request_head,
        "request_body": request_body
    }
    return request_data_to_eap(methodName, data)


def request_eqp_current_lot_report():
    """
    設備上報當最近要生產的5筆LotID(1是最快要生產), 當lot生產完成, 後面排序Lot要調整順序後上報
    呼叫時機：當設備與Host AP Server可連線，設備Lot有新增或結束, 則呼叫WebAPI。
    設備上報當前準備生產的批號ID(包含使用中的)
    新增的时候,使用append,做完结束的时候使用pop(0)的方式,其实这里使用队列是最好的.
    @return:
    """
    methodName = "EquipmentCurrentLotReport"
    requestHead = {
        "function_name": methodName,
        "eqp_id": ec.eqpId,
        "time_stamp": eap_tool.get_time_stamp(),
        "trx_id": eap_tool.get_trx_id()
    }
    res, data = db.get_lot_command_download_info()
    if res != "ok":
        debug_eap(data)
        return data
    dataFirstFive = data[:5]
    lotIdList = [order.get("lot_id", "") for order in dataFirstFive]
    prodListLen = len(dataFirstFive)
    reqeustBody = {
        "lotId_1": lotIdList[0] if prodListLen > 0 else "",
        "lotId_2": lotIdList[1] if prodListLen > 1 else "",
        "lotId_3": lotIdList[2] if prodListLen > 2 else "",
        "lotId_4": lotIdList[3] if prodListLen > 3 else "",
        "lotId_5": lotIdList[4] if prodListLen > 4 else "",
    }
    data = {
        "request_head": requestHead,
        "request_body": reqeustBody
    }
    return request_data_to_eap(methodName, data)


if __name__ == '__main__':
    request_alarm_report(AlarmType.S,1)